#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

#include "tyan.h"
#include "tyn_utils.h"
#include "tyn_exsorter.h"
#include "qsort.h"

#define TYN_DECLARE_ATTR(BITS, TYPE)    \
typedef struct attr##BITS##_##TYPE {     \
    TYPE value;                         \
    uint##BITS##_t document_id;         \
} attr##BITS##_##TYPE;

#define TYN_DECLARE_ATTR_CMP(BITS, TYPE)        \
int tyn_cmp_attr##BITS##_##TYPE(attr##BITS##_##TYPE *a, attr##BITS##_##TYPE *b) {                \
    return (a->value > b->value) || (a->value == b->value && a->document_id > b->document_id);     \
} \

#define TYN_DECLARE_NODE_ATTR_CMP(BITS, TYPE)   \
int tyn_cmp_node_attr##BITS##_##TYPE(tyn_exsorter_node_t *a, tyn_exsorter_node_t *b) {           \
    return tyn_cmp_attr##BITS##_##TYPE((attr##BITS##_##TYPE *)b->data, (attr##BITS##_##TYPE *)a->data); \
} \
/*
TYN_DECLARE_ATTR(32, int8_t)
TYN_DECLARE_ATTR(32, int16_t)
TYN_DECLARE_ATTR(32, int32_t)
TYN_DECLARE_ATTR(32, int64_t)
TYN_DECLARE_ATTR(32, float)
TYN_DECLARE_ATTR_CMP(32, int8_t)
TYN_DECLARE_ATTR_CMP(32, int16_t)
TYN_DECLARE_ATTR_CMP(32, int32_t)
TYN_DECLARE_ATTR_CMP(32, int64_t)
TYN_DECLARE_ATTR_CMP(32, float)

TYN_DECLARE_NODE_ATTR_CMP(32, int8_t)
TYN_DECLARE_NODE_ATTR_CMP(32, int16_t)
TYN_DECLARE_NODE_ATTR_CMP(32, int32_t)
TYN_DECLARE_NODE_ATTR_CMP(32, int64_t)
TYN_DECLARE_NODE_ATTR_CMP(32, float)
*/
#define QUOTE(name) name

#define N1 TYN_ATTR_
#define N2 INT32_T

#define TYN_INIT_ATTR_EXSORTER(BITS, TYPE) \
    char **attr##BITS##_##TYPE##_tmpnams = (char **)malloc( sizeof(char *) * tyn_config_index->num_attr##BITS##_##TYPE##_fields); \
    FILE **attr##BITS##_##TYPE##_tmpfps = (FILE **)malloc( sizeof(FILE *) * tyn_config_index->num_attr##BITS##_##TYPE##_fields); \
    tyn_exsorter_t **attr##BITS##_##TYPE##_exsorters = (tyn_exsorter_t **)malloc( sizeof(tyn_exsorter_t *) * tyn_config_index->num_attr##BITS##_##TYPE##_fields); \
    if(tyn_config_index->num_attr##BITS##_##TYPE##_fields) { \
        for( int i = 0; i < tyn_config_index->num_attr##BITS##_##TYPE##_fields; i++) { \
            *(attr##BITS##_##TYPE##_tmpnams + i) = (char *)malloc( 32 ); \
            sprintf(*(attr##BITS##_##TYPE##_tmpnams + i), "%08x_%08x%08x.tyt", TYN_HASH_ATTR_INT32, tyn_config_index->index_name_hash, *(tyn_config_index->attr##BITS##_##TYPE##_field_hashes + i)); \
            *(attr##BITS##_##TYPE##_tmpfps + i) = fopen(*(attr##BITS##_##TYPE##_tmpnams + i), "w+b"); \
            *(attr##BITS##_##TYPE##_exsorters + i) = tyn_exsorter_create(QUOTE(N1), buffer_size, sizeof(attr##BITS##_##TYPE), tyn_cmp_attr##BITS##_##TYPE, tyn_cmp_node_attr##BITS##_##TYPE, *(attr##BITS##_##TYPE##_tmpfps + i), attr##BITS##_fp); \
        } \
    } 
    

typedef struct item {
    void *item;
} item;

int main() {

    
    
    char *s = "-123456987654321";
    int64_t a = tyn_strntol(s, 16);
    printf("sizeof i %d\n", sizeof(a));
    printf("a: %d\n", (int)a);
    
    printf("sizeof bool: %d\n", sizeof(bool));
    
    printf("#define TYN_TYH_SIGN %uu\n", tyn_hash32("TYN_TYH_SIGN", 12));
    printf("#define TYN_TYD_SIGN %uu\n", tyn_hash32("TYN_TYD_SIGN", 12));
    printf("#define TYN_TYF_SIGN %uu\n", tyn_hash32("TYN_TYF_SIGN", 12));
    printf("#define TYN_TYP_SIGN %uu\n", tyn_hash32("TYN_TYP_SIGN", 12));
    printf("#define TYN_TYI_SIGN %uu\n", tyn_hash32("TYN_TYI_SIGN", 12));
    
    printf("#define TYN_TERM32_T %uu\n", tyn_hash32("TYN_TERM32_T", 12));
    printf("#define TYN_TERM64_T %uu\n", tyn_hash32("TYN_TERM64_T", 12));
    
    
    printf("#define TYN_DOC_ID_T %uu\n", tyn_hash32("DOC_ID_T", 8));
    printf("#define TYN_ATTR32_T %uu\n", tyn_hash32("ATTR32_T", 8));
    printf("#define TYN_ATTR64_T %uu\n", tyn_hash32("ATTR64_T", 8));
    
    printf("#define TYN_DOC_ID32_T %uu\n", tyn_hash32("DOC_ID32_T", 10));
    printf("#define TYN_DOC_ID64_T %uu\n", tyn_hash32("DOC_ID64_T", 10));
    printf("#define TYN_FULLTEXT_T %uu\n", tyn_hash32("FULLTEXT_T", 10));
    printf("#define TYN_ATTR_INT_T %uu\n", tyn_hash32("ATTR_INT_T", 10));
    
    printf("#define TYN_ATTR_UINT8_T %uu\n", tyn_hash32("ATTR_UINT8_T", 12));
    printf("#define TYN_ATTR_UINT8_T %uu\n", tyn_hash32("ATTR_UINT8_T", 12));
    printf("#define TYN_ATTR_UINT16_T %uu\n", tyn_hash32("ATTR_UINT16_T", 13));
    printf("#define TYN_ATTR_UINT32_T %uu\n", tyn_hash32("ATTR_UINT32_T", 13));
    printf("#define TYN_ATTR_UINT64_T %uu\n", tyn_hash32("ATTR_UINT64_T", 13));
    printf("#define TYN_ATTR_INT8_T %uu\n", tyn_hash32("ATTR_INT8_T", 11));
    printf("#define TYN_ATTR_INT16_T %uu\n", tyn_hash32("ATTR_INT16_T", 12));
    printf("#define TYN_ATTR_INT32_T %uu\n", tyn_hash32("ATTR_INT32_T", 12));
    printf("#define TYN_ATTR_INT64_T %uu\n", tyn_hash32("ATTR_INT64_T", 12));
    printf("#define TYN_ATTR_FLOAT_T %uu\n", tyn_hash32("ATTR_FLOAT_T", 12));
    printf("#define TYN_ATTR_DOUBLE_T %uu\n", tyn_hash32("ATTR_DOUBLE_T", 13));
    printf("#define TYN_ATTR_TIMESTAMP_T %uu\n", tyn_hash32("ATTR_TIMESTAMP_T", 16));
    
    printf("#define TYN_ATTR32_INT_T %uu\n", tyn_hash32("ATTR32_INT_T", 12));
    printf("#define TYN_ATTR32_UINT8_T %uu\n", tyn_hash32("ATTR32_UINT8_T", 14));
    printf("#define TYN_ATTR32_UINT16_T %uu\n", tyn_hash32("ATTR32_UINT16_T", 15));
    printf("#define TYN_ATTR32_UINT32_T %uu\n", tyn_hash32("ATTR32_UINT32_T", 15));
    printf("#define TYN_ATTR32_UINT64_T %uu\n", tyn_hash32("ATTR32_UINT64_T", 15));
    printf("#define TYN_ATTR32_INT8_T %uu\n", tyn_hash32("ATTR32_INT8_T", 13));
    printf("#define TYN_ATTR32_INT16_T %uu\n", tyn_hash32("ATTR32_INT16_T", 14));
    printf("#define TYN_ATTR32_INT32_T %uu\n", tyn_hash32("ATTR32_INT32_T", 14));
    printf("#define TYN_ATTR32_INT64_T %uu\n", tyn_hash32("ATTR32_INT64_T", 14));
    printf("#define TYN_ATTR32_FLOAT_T %uu\n", tyn_hash32("ATTR32_FLOAT_T", 14));
    printf("#define TYN_ATTR32_DOUBLE_T %uu\n", tyn_hash32("ATTR32_DOUBLE_T", 15));
    printf("#define TYN_ATTR32_TIMESTAMP_T %uu\n", tyn_hash32("ATTR32_TIMESTAMP_T", 18));
    
    printf("#define TYN_ATTR64_INT_T %uu\n", tyn_hash32("ATTR64_INT_T", 14));
    printf("#define TYN_ATTR64_UINT8_T %uu\n", tyn_hash32("ATTR64_UINT8_T", 14));
    printf("#define TYN_ATTR64_UINT16_T %uu\n", tyn_hash32("ATTR64_UINT16_T", 15));
    printf("#define TYN_ATTR64_UINT32_T %uu\n", tyn_hash32("ATTR64_UINT32_T", 15));
    printf("#define TYN_ATTR64_UINT64_T %uu\n", tyn_hash32("ATTR64_UINT64_T", 15));
    printf("#define TYN_ATTR64_INT8_T %uu\n", tyn_hash32("ATTR64_INT8_T", 13));
    printf("#define TYN_ATTR64_INT16_T %uu\n", tyn_hash32("ATTR64_INT16_T", 14));
    printf("#define TYN_ATTR64_INT32_T %uu\n", tyn_hash32("ATTR64_INT32_T", 14));
    printf("#define TYN_ATTR64_INT64_T %uu\n", tyn_hash32("ATTR64_INT64_T", 14));
    printf("#define TYN_ATTR64_FLOAT_T %uu\n", tyn_hash32("ATTR64_FLOAT_T", 14));
    printf("#define TYN_ATTR64_DOUBLE_T %uu\n", tyn_hash32("ATTR64_DOUBLE_T", 15));
    printf("#define TYN_ATTR64_TIMESTAMP_T %uu\n", tyn_hash32("ATTR64_TIMESTAMP_T", 18));
    
}